package com.wh.minio.service.impl;

import cn.hutool.core.util.IdUtil;
import com.wh.minio.MinioConfig;
import com.wh.org.exception.BusinessException;
import com.wh.org.exception.SystemException;
import com.wh.minio.service.IMinIoFileService;
import io.minio.*;
import io.minio.errors.MinioException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

@Service
@Slf4j
public class MinIoFileServiceImpl implements IMinIoFileService {

    @Autowired
    private MinioConfig minioConfig;

    @Autowired
    private MinioClient minioClient;

    /**
     * 文件上传至Minio
     */
    @Override
    public String  upload(MultipartFile file) {
        InputStream inputStream = null;
        if (file.isEmpty()) {
            // 调试输出文件对象信息
            throw new SystemException("接收到的文件对象为空！");
        }
        //创建Minio的连接对象
        String bucketName = minioConfig.getBucketName();
        try {
            //获取文件上传输入流
            inputStream = file.getInputStream();
            //判断文件存储的桶是否存在
            boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!found) {
                //如果桶不存在则创建通
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
            //获取要上传文件的文件名
            String fileName = file.getOriginalFilename();
            //整理文件名: yyyy/MM/dd/UUID.文件后缀名
            String objectName = new SimpleDateFormat("yyyy/MM/dd/").format(new Date()) + IdUtil.fastSimpleUUID()
                    + fileName.substring(fileName.lastIndexOf("."));
            //文件上传
            //由于使用的是SpringBoot与之进行集成 上传的时候拿到的是MultipartFile 需要通过输入输出流的方式进行添加

            PutObjectArgs objectArgs = PutObjectArgs.builder().object(objectName)
                    .bucket(bucketName)
                    .contentType(file.getContentType())
                    .stream(file.getInputStream(), file.getSize(), -1).build();
            minioClient.putObject(objectArgs);
            //封装访问的url给前端(例如: http://127.0.0.1/blog/java.png)
            String fileUrl = minioConfig.getEndpoint() + "/" + minioConfig.getBucketName() + "/" + objectName;
            return fileUrl;
        } catch (Exception e) {
            throw new SystemException("文件上传失败!");
        } finally {
            //防止内存泄漏
            if (inputStream != null) {
                try {
                    inputStream.close(); // 关闭流
                } catch (IOException e) {
                    throw new SystemException("关闭IO流失败!");
                }
            }
        }
    }

    //删除文件
    @Override
    public void delete(String picUrl) {
        //1.处理路径
        picUrl = trimBucketUrlPath(picUrl);
        //2.删除文件
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(picUrl).build());
        } catch (Exception e) {
            new BusinessException("删除失败");
        }
    }

    //下载文件
    @Override
    public InputStream downloadFile(String picUrl) {
        //1.处理路径
        picUrl = trimBucketUrlPath(picUrl);
        //2.开始下载
        try {
            // 返回文件流
            return minioClient.getObject(GetObjectArgs.builder().bucket(minioConfig.getBucketName()).object(picUrl).build());
        } catch (Exception e) {
            new BusinessException("下载失败");
        }
        return null;
    }

    /**
     * 处理路径. 原完整路径 -> 文件路径
     * @param picUrl 原完整路径
     * @return 文件路径
     */
    private String trimBucketUrlPath(String picUrl) {
        //1.处理url: 把_换为/
        //  原路径: http:__127.0.0.1:9000_blog_2023_06_07_aaa.jpg
        //  新路径: http://127.0.0.1:9000/blog/2023/06/07/aaa.jpg
        picUrl = picUrl.replace("_", "/");
        //2.处理url: 去掉前缀("http://127.0.0.1:9000/blog/")
        //  原路径: http://127.0.0.1:9000/blog/2023/06/07/aaa.jpg
        //  新路径: 2023/06/07/aaa.jpg
        String prefix = minioConfig.getEndpoint() + "/" + minioConfig.getBucketName() + "/";
        picUrl = picUrl.replace(prefix, "");
        return picUrl;
    }

}
